package org.fastiot.protocol.group

import grails.databinding.BindUsing
import org.fastiot.protocol.codec.BitOutputStream
import org.fastiot.protocol.codec.BitSource

/**
 * 复合编组
 */
class Composite implements Groupable {

    /**
     * 隶属（结构/单元）/父类型
     */
    @BindUsing({ obj, source ->
        Affiliation.byValue(Integer.parseInt(source["parentType"] as String))
    })
    Affiliation parentType
    /**
     * 隶属（结构/单元）代码
     */
    Integer parentCode
    /**
     * 隶属（结构/单元）代码（Hex）
     */
    String hexParentCode

    Integer code
    String hexCode
    /**
     * 编组标识符
     */
    String dataIdentifier
    /**
     * 编组名称
     */
    String name

    /**
     * 内置单元类型
     */
    @BindUsing({ obj, source ->
        Groupable.Type.byValue(Integer.parseInt(source["embeddedGroupType"] as String))
    })
    Groupable.Type embeddedGroupType
    /**
     * 内置单元隶属代码
     * 采用非持久化字段，同步code，保持多种编组单元风格统一。
     */
    Integer embeddedGroupAffiliatedCode

    boolean enabled = false

    String remark
    Date dateCreated
    Date lastUpdated

    static transients = ['hexParentCode', 'hexCode', 'embeddedGroupAffiliatedCode']

    static constraints = {
        parentType(nullable: false, inList: Affiliation.values().toList())
        parentCode(nullable: false)
        hexParentCode(nullable: false, matches: /[a-fA-F0-9]+/)
        code(nullable: false, min: 0)
        hexCode(blank: false, matches: /[a-fA-F0-9]+/)
        dataIdentifier(blank: false)
        name(blank: false, unique: true)
        embeddedGroupType(nullable: false, inList: Groupable.Type.values().toList())
        embeddedGroupAffiliatedCode(nullable: true, min: 0)
        enabled(blank: false)
        remark(nullable: true, widget: 'textarea')
    }

    static mapping = {
        remark type: 'text'
    }

    def beforeValidate() {
        if (hexParentCode && !parentCode)
            parentCode = Integer.parseInt(hexParentCode, 16)

        if (hexCode && !code)
            code = Integer.parseInt(hexCode, 16)

        if(!embeddedGroupAffiliatedCode && code)
            embeddedGroupAffiliatedCode = code
    }

    def afterLoad() {
        if (parentCode)
            hexParentCode = Integer.toHexString(parentCode)

        if (code)
            hexCode = Integer.toHexString(code)

        embeddedGroupAffiliatedCode = code
    }

    @Override
    void decode(final BitSource bitSource, final Map contents) {
        throw new UnsupportedOperationException("The method is not implemented")
    }

    @Override
    void encode(final BitOutputStream bitOutput, final Map contents) {
        throw new UnsupportedOperationException("The method is not implemented")
    }
}
